﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Suucha.Expressions;
using Newtonsoft.Json;

namespace Suucha.Expression.Tests
{
    /// <summary>
    /// ExpressionTests 的摘要说明
    /// </summary>
    [TestClass]
    public class ExpressionTests
    {
        public ExpressionTests()
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文，该上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试特性
        //
        // 编写测试时，可以使用以下附加特性:
        //
        // 在运行类中的第一个测试之前使用 ClassInitialize 运行代码
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // 在类中的所有测试都已运行之后使用 ClassCleanup 运行代码
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // 在运行每个测试之前，使用 TestInitialize 来运行代码
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // 在每个测试运行完之后，使用 TestCleanup 来运行代码
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestNormalExpression()
        {
            List<TestClass2> list = TestClass2.CreateTestData();

            SuuchaExpression expression = SuuchaExpression.Equal("Code", "1.1");
            var result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(1, result.Count);

            expression = SuuchaExpression.NotEqual("Code", "1.1");
            result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(1, result.Count);

            expression = SuuchaExpression.Equal(new SuuchaMemberExpression("Code"), new SuuchaConstantExpression("1.1"));
            result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(1, result.Count);

            expression = SuuchaExpression.Like(new SuuchaMemberExpression("Code"), new SuuchaConstantExpression("%.1"));
            result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(2, result.Count);

            expression = SuuchaExpression.And(SuuchaExpression.Equal(new SuuchaConstantExpression(1), new SuuchaConstantExpression(1)), SuuchaExpression.Equal("Code", "1.1"));
            result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(1, result.Count);

            expression = SuuchaExpression.In(new SuuchaMemberExpression("Code"), new SuuchaConstantExpression("1.1,2.1"));
            result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(2, result.Count);
        }

        [TestMethod]
        public void TestOrderByExpression()
        {
            List<TestClass1> list = TestClass2.CreateTestData()[0].TestClass1List;

            var result = list.AsQueryable().OrderBy(SuuchaOrderBy.OrderByDescending("Order")).ToList();
            Assert.AreEqual(3, result[0].Order);
            Assert.AreEqual(2, result[1].Order);
            Assert.AreEqual(1, result[2].Order);

            result = list.AsQueryable().OrderBy(SuuchaOrderBy.OrderBy("Name").ThenBy("Order")).ToList();
            Assert.AreEqual(1, result[0].Order);
            Assert.AreEqual(3, result[1].Order);
            Assert.AreEqual(2, result[2].Order);

            result = list.AsQueryable().OrderBy(SuuchaOrderBy.OrderBy("Name").ThenByDescending("Order")).ToList();
            Assert.AreEqual(3, result[0].Order);
            Assert.AreEqual(1, result[1].Order);
            Assert.AreEqual(2, result[2].Order);

            result = list.AsQueryable().OrderBy(SuuchaOrderBy<TestClass1>.OrderBy(t => t.Name).ThenByDescending(t => t.Order)).ToList();
            Assert.AreEqual(3, result[0].Order);
            Assert.AreEqual(1, result[1].Order);
            Assert.AreEqual(2, result[2].Order);
        }

        [TestMethod]
        public void TestSelectMany()
        {
            List<TestClass2> list = TestClass2.CreateTestData();

            SuuchaExpression expression = SuuchaExpression.Equal("TestClass1List.Name", "A");
            var result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(1, result.Count);

            expression = SuuchaExpression.Equal("TestClass1List.Name", "C");
            result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(2, result.Count);

        }

        [TestMethod]
        public void TestJson()
        {
            List<TestClass2> list = TestClass2.CreateTestData();

            SuuchaExpression expression = SuuchaExpression.And(SuuchaExpression.Equal(new SuuchaConstantExpression(1), new SuuchaConstantExpression(1)), SuuchaExpression.Equal("Code", "1.1"));

            string json = expression.ToJson();

            var expFromJosn = SuuchaExpression.FromJson(json);
            var result = list.AsQueryable().Where(expFromJosn).ToList();
            Assert.AreEqual(1, result.Count);

            SearchParameters search = new SearchParameters();
            search.Condition = expression;
            search.Sorts = SuuchaOrderBy.OrderBy("Name").ThenByDescending("Code");

            json = search.ToJson();

            var s = JsonConvert.DeserializeObject<SearchParameters>(json);
            Assert.AreEqual(2, s.Sorts.Count);
        }

        [TestMethod]
        public void TestJson1()
        {
            SearchParameters search = new SearchParameters();
            search.Condition = null;
            search.Sorts = SuuchaOrderBy.OrderBy("Name").ThenByDescending("Code");

            string json = search.ToJson();

            var s = SearchParameters.FromJson(json);
            Assert.AreEqual(2, s.Sorts.Count);
            Assert.AreEqual(null, s.Condition);
        }

        [TestMethod]
        public void TestStringCompare()
        {
            List<TestClass2> list = TestClass2.CreateTestData();

            SuuchaExpression expression = SuuchaExpression.LessThanOrEqual("Code", "1.1");
            var result = list.AsQueryable().Where(expression).ToList();
            Assert.AreEqual(1, result.Count);
        }
    }
}
